package com.lj.back.manage.scaffold.module.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.lj.back.manage.scaffold.common.DTO.PageQuery;
import com.lj.back.manage.scaffold.common.util.Assert;
import com.lj.back.manage.scaffold.common.util.CommonUtil;
import com.lj.back.manage.scaffold.common.util.QueryWrapperUtil;
import com.lj.back.manage.scaffold.module.sys.DO.SysRoleDO;
import com.lj.back.manage.scaffold.module.sys.DO.SysUserRoleDO;
import com.lj.back.manage.scaffold.module.sys.DTO.SysMenuDTO;
import com.lj.back.manage.scaffold.module.sys.DTO.SysRoleDTO;
import com.lj.back.manage.scaffold.module.sys.constant.UserConstant;
import com.lj.back.manage.scaffold.module.sys.dao.SysRoleDao;
import com.lj.back.manage.scaffold.module.sys.dao.SysRoleMenuDao;
import com.lj.back.manage.scaffold.module.sys.dao.SysUserRoleDao;
import com.lj.back.manage.scaffold.module.sys.service.SysMenuService;
import com.lj.back.manage.scaffold.module.sys.service.SysPermService;
import com.lj.back.manage.scaffold.module.sys.service.SysRoleService;
import com.lj.back.manage.scaffold.module.sys.util.SysCommonUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 后台管理---角色service实现类
 * @author lv
 * @version 1.0.0
 */
@Service
@AllArgsConstructor
public class SysRoleServiceImpl implements SysRoleService {

    private final SysRoleDao sysRoleDao;

    private final SysMenuService sysMenuService;

    private final SysPermService sysPermService;

    private final SysUserRoleDao sysUserRoleDao;

    private final SysRoleMenuDao sysRoleMenuDao;


    @Override
    public Set<SysRoleDTO> listRoleByUser(Long userId) {
        Set<SysRoleDTO> roleDos = sysRoleDao.selectRoleByUser(userId);;
        return roleDos;
    }

    @Override
    public Set<String> listRolePermissions(Long roleId) {
        Set<SysMenuDTO> menuDTOS = sysMenuService.listMenuByRole(roleId);
        if (menuDTOS == null || menuDTOS.isEmpty()){
            return null;
        }
        Set<String> permissionsByRole = new HashSet<>();
        menuDTOS.stream().forEach(menuVO->{
            Set<String> permissions = sysPermService.listPermissionsByMenu(menuVO.getId());
            if (permissions != null && !permissions.isEmpty()){
                permissionsByRole.addAll(permissions);
            }
        });
        return permissionsByRole;
    }

    @Override
    public int addRoleToUser(Long roleId, Long userId) {
        SysUserRoleDO sysUserRoleDO = new SysUserRoleDO();
        sysUserRoleDO.setUserId(userId);
        sysUserRoleDO.setRoleId(roleId);
        int count = sysUserRoleDao.insert(sysUserRoleDO);
        return count;
    }

    @Override
    public LinkedHashSet<SysRoleDTO> listRoles(){
        List<SysRoleDO> sysRoleDOS = sysRoleDao.selectList(QueryWrapperUtil.getOrderByDescQueryWrapper());
        if (CollectionUtil.isEmpty(sysRoleDOS)){
            return null;
        }
        LinkedHashSet<SysRoleDTO> sysRoleDTOS = sysRoleDOS.stream().map(sysRoleDO -> BeanUtil.copyProperties(sysRoleDO, SysRoleDTO.class))
                .collect(Collectors.toCollection(LinkedHashSet::new));
        return sysRoleDTOS;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Long addRole(SysRoleDTO sysRoleDTO){
        SysRoleDO sysRoleDO = BeanUtil.copyProperties(sysRoleDTO, SysRoleDO.class);
        sysRoleDO.setCreateUserId(SysCommonUtil.getUserId());
        sysRoleDao.insert(sysRoleDO);
        Set<Long> menuIds = sysRoleDTO.getMenuIds();
        if (CollectionUtil.isNotEmpty(menuIds)){
            sysRoleDao.insertRoleMenu(sysRoleDO.getId(),sysRoleDTO.getMenuIds());
        }
        return sysRoleDO.getId();
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean removeRole(Long roleId){
        SysRoleDO sysRoleDO = sysRoleDao.selectById(roleId);
        Assert.assertNotNull(sysRoleDO,"角色ID不存在");
        Assert.assertIsTrue(sysRoleDO.getCreateUserId() == UserConstant.SYSTEM_CREATE_ROLE_ID,"不允许删除系统内建角色");
        //删除用户角色关联关系
        sysUserRoleDao.deleteUserRoleByRoleId(roleId);
        //删除角色菜单管理关系
        sysRoleMenuDao.deleteRoleMenuByRoleId(roleId);
        //删除角色
        sysRoleDao.deleteById(roleId);
        return true;
    }

    @Override
    public SysRoleDTO getRoleInfo(Long roleId){
        SysRoleDO sysRoleDO = sysRoleDao.selectById(roleId);
        Assert.assertNotNull(sysRoleDO,"角色不存在");
        SysRoleDTO sysRoleDTO = BeanUtil.copyProperties(sysRoleDO, SysRoleDTO.class);
        Set<SysMenuDTO> sysMenuDTOS = sysMenuService.listMenuByRole(roleId);
        if (CollectionUtil.isNotEmpty(sysMenuDTOS)){
            Set<Long> menuIds = sysMenuDTOS.stream()
                    .map(sysMenuDTO -> sysMenuDTO.getId())
                    .collect(Collectors.toSet());
            sysRoleDTO.setMenuIds(menuIds);
        }
        return sysRoleDTO;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean updateRole(SysRoleDTO sysRoleDTO){
        //更新基本信息
        SysRoleDO sysRoleDO = BeanUtil.copyProperties(sysRoleDTO, SysRoleDO.class);
        sysRoleDao.updateById(sysRoleDO);
        //删除关联菜单
        sysRoleMenuDao.deleteRoleMenuByRoleId(sysRoleDTO.getId());
        Set<Long> menuIds = sysRoleDTO.getMenuIds();
        if (CollectionUtil.isNotEmpty(menuIds)){
            //新增菜单
            sysRoleDao.insertRoleMenu(sysRoleDTO.getId(),menuIds);
        }
        return true;
    }

    @Override
    public IPage<SysRoleDTO> listRoles(PageQuery pageQuery){
        QueryWrapper<SysRoleDO> queryWrapper = QueryWrapperUtil.getPageQueryWrapper(SysRoleDO.class, pageQuery, "name");
        IPage<SysRoleDO> sysRoleDOPage = sysRoleDao.selectPage(QueryWrapperUtil.getPage(pageQuery),queryWrapper);
        return CommonUtil.pageBeanConvert(sysRoleDOPage, SysRoleDTO.class);
    }
}
